package com.lmaor.project.commons.parameters;

import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class ParamClass {
	private Map<String, Object> classMap = new HashMap<String, Object>(128);
	private ParamInjector paramInjector;
	private Object orherAttr;
	private Object orherAttr2;
	private Object orherAttr3;
	private Object orherAttr4;
	private Object orherAttr5;
	private Object orherAttr6;
	public ParamClass() {
		put(this.getClass(), this);
	}
	
	public ParamClass(ParamInjector paramInjector) {
		this();
		this.paramInjector = paramInjector;
	}
	private void putClass(Class clazz,Object value){
		classMap.put(clazz.getName(), value);
	}
	public ParamType put(Class clazz,Object value){
		putClass(clazz, value);
		return new ParamType(this, value);
	}
	public ParamType put(String key,Object value){
		classMap.put(key, value);
		return new ParamType(this, value);
	}
	
	public ParamType put(Object value){
		if(value!=null){
			putClass(value.getClass(), value);
		}
		return new ParamType(this, value);
	}
	public Object get(Object key){
		if(key instanceof Class){
			return classMap.get(((Class)key).getName());
		}
		
		return classMap.get(String.valueOf(key));
	}
	final Object[] zero={};
	public Object[] getParams(AccessibleObject executable){
		Class[] paramClasses = null;
		Annotation[][] parameterannotationarr2 = null;
		if(executable instanceof Method){
			paramClasses = ((Method)executable).getParameterTypes();
			parameterannotationarr2 = ((Method)executable).getParameterAnnotations();
		}else if(executable instanceof Constructor){
			paramClasses = ((Constructor)executable).getParameterTypes();
			parameterannotationarr2 = ((Constructor)executable).getParameterAnnotations();
		}
		if(paramClasses == null||paramClasses.length==0){
			return zero;
		}
		
		Object[] params = new Object[paramClasses.length];
		ParameterAnnotations parameterAnnotations = new ParameterAnnotations(parameterannotationarr2);
		// 方法注解
		MethodAnnotation methodAnnotation = new MethodAnnotation(executable.getDeclaredAnnotations());
		for (int i = 0; i < paramClasses.length; i++) {
			// 参数注解
			ParameterAnnotation parameterAnnotation = parameterAnnotations.getParameterAnnotation(i);
			Class paramClass = paramClasses[i];
			Object param = null;
			if(paramInjector!=null){
				param = paramInjector.getObject(executable, paramClass, methodAnnotation, parameterAnnotation,this);
			}
			if(param == null){
				param = get(paramClass);
			}
			if(param == null){
				param = getDefault(paramClass);
			}
			params[i] = param;
		}
		return params;
	}
	
	public Object getDefault(Class paramClass){
		if(Number.class.isAssignableFrom(paramClass)){
			return 0;
		}
		if(paramClass.isPrimitive()){
			if(paramClass == Boolean.class||paramClass == boolean.class){
				return false;
			}
			return 0;
		}
		
		return null;
	}
	public static class ParamType{
		ParamClass paramClass;
		Object value;
		
		public ParamType(ParamClass paramClass, Object value) {
			this.paramClass = paramClass;
			this.value = value;
		}
		public ParamType addClass(Class type){
			return setClass(type);
		}
		public ParamType setClass(Class type){
			paramClass.putClass(type, value);
			return this;
		}
		public ParamType put(Class clazz,Object value){
			return paramClass.put(clazz, value);
		}
		public ParamType put(Object value){
			return paramClass.put(value);
		}
		public ParamType put(String key,Object value){
			return paramClass.put(key, value);
		}
	}
	public void setOrherAttr(Object orherAttr) {
		this.orherAttr = orherAttr;
	}
	public Object getOrherAttr() {
		return orherAttr;
	}
	public Object getOrherAttr2() {
		return orherAttr2;
	}
	public void setOrherAttr2(Object orherAttr2) {
		this.orherAttr2 = orherAttr2;
	}
	public Object getOrherAttr3() {
		return orherAttr3;
	}
	public void setOrherAttr3(Object orherAttr3) {
		this.orherAttr3 = orherAttr3;
	}
	public Object getOrherAttr4() {
		return orherAttr4;
	}
	public void setOrherAttr4(Object orherAttr4) {
		this.orherAttr4 = orherAttr4;
	}
	public Object getOrherAttr5() {
		return orherAttr5;
	}
	public void setOrherAttr5(Object orherAttr5) {
		this.orherAttr5 = orherAttr5;
	}
	public Object getOrherAttr6() {
		return orherAttr6;
	}
	public void setOrherAttr6(Object orherAttr6) {
		this.orherAttr6 = orherAttr6;
	}
	public static void main(String[] args) {
		System.out.println(Number.class.isAssignableFrom(Integer.class));

	}
}
